#!/usr/bin/python
# -*- coding: utf-8 -*-

import logging
from google.appengine.ext import webapp, db
from google.appengine.ext.webapp.util import run_wsgi_app
import bts.index
from bts.models import *
from indexed_models import *

logging.getLogger().setLevel(logging.INFO)


class IndexModel(webapp.RequestHandler):
    """RequestHandler for processing model index requests from a task queue.
    """

    def post(self):
        (self.response.headers)['Content-Type'] = 'text/plain'
        key = self.request.get('key')
        model = db.get(key)
        if model:
            bts.index.update_model(model)
            self.response.out.write('Indexed Model under key %s' % key)
        else:
            self.response.out.write('No Model found to index under key %s' %
                                    key)


class RemoveModel(webapp.RequestHandler):
    """RequestHandler for processing model index removals from a task queue.
    """
    def post(self):
        (self.response.headers)['Content-Type'] = 'text/plain'
        key = self.request.get('key')
        bts.index.remove_model(key)
        self.response.out.write('Removed Model under key %s' % key)


class MergeUpdates(webapp.RequestHandler):
    """Request handler for processing merge update requests from a task queue.
    """
    def post(self):
        (self.response.headers)['Content-Type'] = 'text/plain'
        term_type = self.request.get('term_type')
        if term_type == 'term_string':
            start_letter = self.request.get('start_letter')
            end_letter = self.request.get('end_letter')
            bts.index.merge_string_updates(start_letter, end_letter)
        else:
            bts.index.merge_updates(term_type)
        self.response.out.write('Merged updates for term_type %s' %
                                term_type)


class KickoffMergeUpdates(webapp.RequestHandler):
    """RequestHandler for periodically kicking off merge updates requests
    based on a CRON job.
    """
    def get(self):
        """
        Splits merging of string updates by character.
        Starts with lowest non-control UTF-8 character and goes through highest UTF-8 character.
        Individual lower case letters each get their own bucket because we expect most terms to start with one of them.
        """
        letters = (u'\u0000,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,\u00FF').split(u',')
        for i in range(0, len(letters)):
            start_letter = letters[i]
            end_letter = None
            if start_letter != u'\u00FF':
                end_letter = letters[i + 1]
            bts.index.request_merge_updates('term_string', start_letter=
                    start_letter, end_letter=end_letter)
        bts.index.request_merge_updates('term_reference')
        bts.index.request_merge_updates('term_integer')
        bts.index.request_merge_updates('term_bool')
        bts.index.request_merge_updates('term_date')
        bts.index.request_merge_updates('term_datetime')
        self.response.out.write('Kicked off merge updates')


class PurgeProcessedTermUpdates(webapp.RequestHandler):
    """Purge processed term updates.
    """
    def get(self):
        bts.index.purge_processed_updates()
        self.response.out.write('Performed purge')

application = webapp.WSGIApplication([('/bts/index-model', IndexModel),
        ('/bts/remove-model', RemoveModel), ('/bts/merge-updates',
        MergeUpdates), ('/bts/kickoff-merge-updates',
        KickoffMergeUpdates), ('/bts/purge-processed-updates',
        PurgeProcessedTermUpdates)], debug=False)


def main():
    run_wsgi_app(application)


def profile_main():

    # This is the main function for profiling
    # We've renamed our original main() above to real_main()

    import cProfile
    import pstats
    import StringIO
    prof = cProfile.Profile()
    prof = prof.runctx("main()", globals(), locals())
    stream = StringIO.StringIO()
    stats = pstats.Stats(prof, stream=stream)
    stats.sort_stats("time")  # Or cumulative
    stats.print_stats(80)  # 80 = how many to print

    # The rest is optional.
    # stats.print_callees()
    # stats.print_callers()

    logging.info("Profile data:\n%s", stream.getvalue())


if __name__ == "__main__":
    profile_main()
